//#include "includes.h"
#include "enc28j60.h"
#include <stdio.h>

static unsigned char Enc28j60Bank;
static unsigned int NextPacketPtr;


unsigned char enc28j60ReadOp(unsigned char op, unsigned char address)
	{
	unsigned char dat = 0;
	
	SPI1_CS_Low();
	
	dat = op | (address & ADDR_MASK);
	SPI1_ReadWrite(dat);
	dat = SPI1_ReadWrite(0xFF);
	// do dummy read if needed (for mac and mii, see datasheet page 29)
	if(address & 0x80)
	    {
		dat = SPI1_ReadWrite(0xFF);
	    }
	// release CS
	SPI1_CS_High();
	return dat;
	}

void enc28j60WriteOp(unsigned char op, unsigned char address, unsigned char data)
	{
	unsigned char dat = 0;
	  
	SPI1_CS_Low();
	// issue write command
	dat = op | (address & ADDR_MASK);
	SPI1_ReadWrite(dat);
	// write data
	dat = data;
	SPI1_ReadWrite(dat);
	SPI1_CS_High();
	}

void enc28j60ReadBuffer(unsigned int len, unsigned char* data)
	{
	SPI1_CS_Low();
	// issue read command
	SPI1_ReadWrite(ENC28J60_READ_BUF_MEM);
	while(len)
		{
        len--;
        // read data
        *data = (unsigned char)SPI1_ReadWrite(0);
        data++;
		}
	*data='\0';
	SPI1_CS_High();
	}

void enc28j60WriteBuffer(unsigned int len, unsigned char* data)
	{
	SPI1_CS_Low();
	// issue write command
	SPI1_ReadWrite(ENC28J60_WRITE_BUF_MEM);
	
	while(len)
		{
		len--;
		SPI1_ReadWrite(*data);
		data++;
		}
	SPI1_CS_High();
	}

void enc28j60SetBank(unsigned char address)
	{
	// set the bank (if needed)
	if((address & BANK_MASK) != Enc28j60Bank)
		{
        // set the bank
        enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
        Enc28j60Bank = (address & BANK_MASK);
		}
	}

unsigned char enc28j60Read(unsigned char address)
	{
	unsigned char read;
	// set the bank
	enc28j60SetBank(address);
	// do the read
	read = enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);

//	printf("Bank %d Reg 0x%02X = 0x%04X\n\r", ((address & BANK_MASK)>>5), (address & ADDR_MASK), read);
	return read;
	}

void enc28j60Write(unsigned char address, unsigned char data)
	{
	// set the bank
	enc28j60SetBank(address);
	// do the write
	enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
	}
void	enc28j60Dump(void)
	{
	printf("\n\rENC20J60 REGS:\n\r");
	printf("EIE\t=\t0x%02X\n\r", enc28j60Read(EIE));
	printf("EIR\t=\t0x%02X\n\r", enc28j60Read(EIR));
	printf("ESTAT\t=\t0x%02X\n\r", enc28j60Read(ESTAT));
	printf("ECON2\t=\t0x%02X\n\r", enc28j60Read(ECON2));
	printf("ECON1\t=\t0x%02X\n\r", enc28j60Read(ECON1));
	printf("\n\rBANK 0\n\r");
	printf("ERDPTL\t=\t0x%02X\n\r", enc28j60Read(ERDPTL));
	printf("ERDPTH\t=\t0x%02X\n\r", enc28j60Read(ERDPTH));
	printf("EWRPTL\t=\t0x%02X\n\r", enc28j60Read(EWRPTL));
	printf("EWRPTH\t=\t0x%02X\n\r", enc28j60Read(EWRPTH));
	printf("ETXSTL\t=\t0x%02X\n\r", enc28j60Read(ETXSTL));
	printf("ETXSTH\t=\t0x%02X\n\r", enc28j60Read(ETXSTH));
	printf("ETXNDL\t=\t0x%02X\n\r", enc28j60Read(ETXNDL));
	printf("ETXNDH\t=\t0x%02X\n\r", enc28j60Read(ETXNDH));
	printf("ERXSTL\t=\t0x%02X\n\r", enc28j60Read(ERXSTL));
	printf("ERXSTH\t=\t0x%02X\n\r", enc28j60Read(ERXSTH));
	printf("ERXNDL\t=\t0x%02X\n\r", enc28j60Read(ERXNDL));
	printf("ERXNDH\t=\t0x%02X\n\r", enc28j60Read(ERXNDH));
	printf("ERXRDPTL\t=\t0x%02X\n\r", enc28j60Read(ERXRDPTL));
	printf("ERXRDPTH\t=\t0x%02X\n\r", enc28j60Read(ERXRDPTH));
	printf("ERXWRPTL\t=\t0x%02X\n\r", enc28j60Read(ERXWRPTL));
	printf("ERXWRPTH\t=\t0x%02X\n\r", enc28j60Read(ERXWRPTH));
	printf("EDMASTL\t=\t0x%02X\n\r", enc28j60Read(EDMASTL));
	printf("EDMASTH\t=\t0x%02X\n\r", enc28j60Read(EDMASTH));
	printf("EDMANDL\t=\t0x%02X\n\r", enc28j60Read(EDMANDL));
	printf("EDMANDH\t=\t0x%02X\n\r", enc28j60Read(EDMANDH));
	printf("EDMADSTL\t=\t0x%02X\n\r", enc28j60Read(EDMADSTL));
	printf("EDMADSTH\t=\t0x%02X\n\r", enc28j60Read(EDMADSTH));
	printf("EDMACSL\t=\t0x%02X\n\r", enc28j60Read(EDMACSL));
	printf("EDMACSH\t=\t0x%02X\n\r", enc28j60Read(EDMACSH));

	printf("\n\rBANK 1\n\r");
	printf("EHT0\t=\t0x%02X\n\r", enc28j60Read(EHT0));
	printf("EHT1\t=\t0x%02X\n\r", enc28j60Read(EHT1));
	printf("EHT2\t=\t0x%02X\n\r", enc28j60Read(EHT2));
	printf("EHT3\t=\t0x%02X\n\r", enc28j60Read(EHT3));
	printf("EHT4\t=\t0x%02X\n\r", enc28j60Read(EHT4));
	printf("EHT5\t=\t0x%02X\n\r", enc28j60Read(EHT5));
	printf("EHT6\t=\t0x%02X\n\r", enc28j60Read(EHT6));
	printf("EHT7\t=\t0x%02X\n\r", enc28j60Read(EHT7));
	printf("EPMM0\t=\t0x%02X\n\r", enc28j60Read(EPMM0));
	printf("EPMM1\t=\t0x%02X\n\r", enc28j60Read(EPMM1));
	printf("EPMM2\t=\t0x%02X\n\r", enc28j60Read(EPMM2));
	printf("EPMM3\t=\t0x%02X\n\r", enc28j60Read(EPMM3));
	printf("EPMM4\t=\t0x%02X\n\r", enc28j60Read(EPMM4));
	printf("EPMM5\t=\t0x%02X\n\r", enc28j60Read(EPMM5));
	printf("EPMM6\t=\t0x%02X\n\r", enc28j60Read(EPMM6));
	printf("EPMM7\t=\t0x%02X\n\r", enc28j60Read(EPMM7));
	printf("EPMCSL\t=\t0x%02X\n\r", enc28j60Read(EPMCSL));
	printf("EPMCSH\t=\t0x%02X\n\r", enc28j60Read(EPMCSH));
	printf("EPMOL\t=\t0x%02X\n\r", enc28j60Read(EPMOL));
	printf("EPMOH\t=\t0x%02X\n\r", enc28j60Read(EPMOH));
	printf("EWOLIE\t=\t0x%02X\n\r", enc28j60Read(EWOLIE));
	printf("EWOLIR\t=\t0x%02X\n\r", enc28j60Read(EWOLIR));
	printf("ERXFCON\t=\t0x%02X\n\r", enc28j60Read(ERXFCON));
	printf("EPKTCNT\t=\t0x%02X\n\r", enc28j60Read(EPKTCNT));

	printf("\n\rBANK 2\n\r");
	printf("MACON1\t=\t0x%02X\n\r", enc28j60Read(MACON1));
	printf("MACON2\t=\t0x%02X\n\r", enc28j60Read(MACON2));
	printf("MACON3\t=\t0x%02X\n\r", enc28j60Read(MACON3));
	printf("MACON4\t=\t0x%02X\n\r", enc28j60Read(MACON4));
	printf("MABBIPG\t=\t0x%02X\n\r", enc28j60Read(MABBIPG));
	printf("MAIPGL\t=\t0x%02X\n\r", enc28j60Read(MAIPGL));
	printf("MAIPGH\t=\t0x%02X\n\r", enc28j60Read(MAIPGH));
	printf("MACLCON1\t=\t0x%02X\n\r", enc28j60Read(MACLCON1));
	printf("MACLCON2\t=\t0x%02X\n\r", enc28j60Read(MACLCON2));
	printf("MAMXFLL\t=\t0x%02X\n\r", enc28j60Read(MAMXFLL));
	printf("MAMXFLH\t=\t0x%02X\n\r", enc28j60Read(MAMXFLH));
	printf("MAPHSUP\t=\t0x%02X\n\r", enc28j60Read(MAPHSUP));
	printf("MICON\t=\t0x%02X\n\r", enc28j60Read(MICON));
	printf("MICMD\t=\t0x%02X\n\r", enc28j60Read(MICMD));
	printf("MIREGADR\t=\t0x%02X\n\r", enc28j60Read(MIREGADR));
	printf("MIWRL\t=\t0x%02X\n\r", enc28j60Read(MIWRL));
	printf("MIWRH\t=\t0x%02X\n\r", enc28j60Read(MIWRH));
	printf("MIRDL\t=\t0x%02X\n\r", enc28j60Read(MIRDL));
	printf("MIRDH\t=\t0x%02X\n\r", enc28j60Read(MIRDH));

	printf("\n\rBANK 3\n\r");
	printf("MAADR1\t=\t0x%02X\n\r", enc28j60Read(MAADR1));
	printf("MAADR0\t=\t0x%02X\n\r", enc28j60Read(MAADR0));
	printf("MAADR3\t=\t0x%02X\n\r", enc28j60Read(MAADR3));
	printf("MAADR2\t=\t0x%02X\n\r", enc28j60Read(MAADR2));
	printf("MAADR5\t=\t0x%02X\n\r", enc28j60Read(MAADR5));
	printf("MAADR4\t=\t0x%02X\n\r", enc28j60Read(MAADR4));
	printf("EBSTSD\t=\t0x%02X\n\r", enc28j60Read(EBSTSD));
	printf("EBSTCON\t=\t0x%02X\n\r", enc28j60Read(EBSTCON));
	printf("EBSTCSL\t=\t0x%02X\n\r", enc28j60Read(EBSTCSL));
	printf("EBSTCSH\t=\t0x%02X\n\r", enc28j60Read(EBSTCSH));
	printf("MISTAT\t=\t0x%02X\n\r", enc28j60Read(MISTAT));
	printf("EREVID\t=\t0x%02X\n\r", enc28j60Read(EREVID));
	printf("ECOCON\t=\t0x%02X\n\r", enc28j60Read(ECOCON));
	printf("EFLOCON\t=\t0x%02X\n\r", enc28j60Read(EFLOCON));
	printf("EPAUSL\t=\t0x%02X\n\r", enc28j60Read(EPAUSL));
	printf("EPAUSH\t=\t0x%02X\n\r", enc28j60Read(EPAUSH));

	}

void 	enc28j60PhyRead(unsigned char address, unsigned short int* data)
{
//	unsigned char tmp;

	// set the PHY register address
	enc28j60Write(MIREGADR, address);

	// set MICMD.MIIRD bit to start read opp.
	enc28j60Write(MICMD, MICMD_MIIRD);

	// wait until PHY write completes
	while(enc28j60Read(MISTAT) & MISTAT_BUSY);

	// clear MICMD.MIIRD bit
	enc28j60Write(MICMD, 0x00);

	*data = (unsigned short int)enc28j60Read(MIRDH)<<8;
	*data += enc28j60Read(MIRDL);
}

void enc28j60PhyWrite(unsigned char address, unsigned short int data)
	{
	// set the PHY register address
	enc28j60Write(MIREGADR, address);
	// write the PHY data
	enc28j60Write(MIWRL, data);
	enc28j60Write(MIWRH, data>>8);
	// wait until the PHY write completes
	while(enc28j60Read(MISTAT) & MISTAT_BUSY)
		{
	    	//Del_10us(1);
			//_nop_();
		}
	}

void 	enc28j60PhyDump(void)
{
	unsigned short int data;

	printf("\n\rPHY REGS:\n\r");
	enc28j60PhyRead(PHCON1, &data);
	printf("PHCON1\t=\t0x%04X\n\r",data);
	enc28j60PhyRead(PHSTAT1, &data);
	printf("PHSTAT1\t=\t0x%04X\n\r",data);
	enc28j60PhyRead(PHHID1, &data);
	printf("PHHID1\t=\t0x%04X\n\r",data);
	enc28j60PhyRead(PHHID2, &data);
	printf("PHHID2\t=\t0x%04X\n\r",data);
	enc28j60PhyRead(PHCON2, &data);
	printf("PHCON2\t=\t0x%04X\n\r",data);
	enc28j60PhyRead(PHSTAT2, &data);
	printf("PHSTAT2\t=\t0x%04X\n\r",data);
	enc28j60PhyRead(PHIE, &data);
	printf("PHIE\t=\t0x%04X\n\r",data);
	enc28j60PhyRead(PHIR, &data);
	printf("PHIR\t=\t0x%04X\n\r",data);
	enc28j60PhyRead(PHLCON, &data);
	printf("PHLCON\t=\t0x%04X\n\r",data);

}

void enc28j60clkout(unsigned char clk)
	{
    //setup clkout: 2 is 12.5MHz:
	enc28j60Write(ECOCON, clk & 0x7);
	}

void enc28j60Init(unsigned char* macaddr)
	{
	// initialize SPI
	SPI1_Init();
	SPI1_CS_High();

    //enc28j60SetSCK();
    //enc28j60HWreset();
	// perform system reset
	enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
//	Del_1ms(250);
	// check CLKRDY bit to see if reset is complete
        // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.
	//while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
	// do bank 0 stuff
	// initialize receive buffer
	// 16-bit transfers, must write low byte first
	// set receive buffer start address
	NextPacketPtr = RXSTART_INIT;
        // Rx start
	enc28j60Write(ERXSTL, RXSTART_INIT&0xFF);
	enc28j60Write(ERXSTH, RXSTART_INIT>>8);
	// set receive pointer address
	enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
	enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);
	// RX end
	enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF);
	enc28j60Write(ERXNDH, RXSTOP_INIT>>8);
	// TX start
	enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
	enc28j60Write(ETXSTH, TXSTART_INIT>>8);
	// TX end
	enc28j60Write(ETXNDL, TXSTOP_INIT&0xFF);
	enc28j60Write(ETXNDH, TXSTOP_INIT>>8);
	// do bank 1 stuff, packet filter:
        // For broadcast packets we allow only ARP packtets
        // All other packets should be unicast only for our mac (MAADR)
        //
        // The pattern to match on is therefore
        // Type     ETH.DST
        // ARP      BROADCAST
        // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
        // in binary these poitions are:11 0000 0011 1111
        // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
	enc28j60Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);
	enc28j60Write(EPMM0, 0x3f);
	enc28j60Write(EPMM1, 0x30);
	enc28j60Write(EPMCSL, 0xf9);
	enc28j60Write(EPMCSH, 0xf7);
        //
        //
	// do bank 2 stuff
	// enable MAC receive
	enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
	// bring MAC out of reset
	enc28j60Write(MACON2, 0x00);
	// enable automatic padding to 60bytes and CRC operations
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);
	// set inter-frame gap (non-back-to-back)
	enc28j60Write(MAIPGL, 0x12);
	enc28j60Write(MAIPGH, 0x0C);
	// set inter-frame gap (back-to-back)
	enc28j60Write(MABBIPG, 0x12);
	// Set the maximum packet size which the controller will accept
        // Do not send packets longer than MAX_FRAMELEN:
	enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);	
	enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8);
	// do bank 3 stuff
	// write MAC address
	// NOTE: MAC address in ENC28J60 is byte-backward
	enc28j60Write(MAADR5, macaddr[0]);	
	enc28j60Write(MAADR4, macaddr[1]);
	enc28j60Write(MAADR3, macaddr[2]);
	enc28j60Write(MAADR2, macaddr[3]);
	enc28j60Write(MAADR1, macaddr[4]);
	enc28j60Write(MAADR0, macaddr[5]);

	printf("MAADR5 = 0x%x\r\n", enc28j60Read(MAADR5));
	printf("MAADR4 = 0x%x\r\n", enc28j60Read(MAADR4));
	printf("MAADR3 = 0x%x\r\n", enc28j60Read(MAADR3));
	printf("MAADR2 = 0x%x\r\n", enc28j60Read(MAADR2));
	printf("MAADR1 = 0x%x\r\n", enc28j60Read(MAADR1));
	printf("MAADR0 = 0x%x\r\n", enc28j60Read(MAADR0));

	enc28j60PhyWrite(PHCON1, PHCON1_PDPXMD);


	// no loopback of transmitted frames
	enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
	// switch to bank 0
	enc28j60SetBank(ECON1);
	// enable interrutps
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
	// enable packet reception
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
	}

void 	enc28j60InitTest(void)
{
	int i;

	SPI1_Init();
	SPI1_CS_High();

	enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);

	for(i=0; i<1000000; i++)
	{
		i++;
		i--;
	}

	enc28j60PhyWrite(PHCON1, PHCON1_PDPXMD);

	// no loopback of transmitted frames
	enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
}

// read the revision of the chip:
unsigned char enc28j60getrev(void)
	{
	return(enc28j60Read(EREVID));
	}

// link status
unsigned char enc28j60linkup(void)
{
  // bit 10 (= bit 2 in upper reg)
	unsigned short int data;
	enc28j60PhyRead(PHSTAT2, &data);

	if(data & PHSTAT2_LSTAT)
		return 1;
	else
		return 0;
}

//void enc28j60PacketSend(unsigned int len, unsigned char* packet)
//	{
//	// Set the write pointer to start of transmit buffer area
//	enc28j60Write(EWRPTL, TXSTART_INIT&0xFF);
//	enc28j60Write(EWRPTH, TXSTART_INIT>>8);
//
//	// Set the TXND pointer to correspond to the packet size given
//	enc28j60Write(ETXNDL, (TXSTART_INIT+len)&0xFF);
//	enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);
//
//	// write per-packet control byte (0x00 means use macon3 settings)
//	enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
//
//	// copy the packet into the transmit buffer
//	enc28j60WriteBuffer(len, packet);
//
//	// send the contents of the transmit buffer onto the network
//	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
//
//    // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
//	if( (enc28j60Read(EIR) & EIR_TXERIF) )
//		{
//        enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
//        }
//	}
void enc28j60PacketSend(unsigned int len, unsigned char* packet)
{
        // Check no transmit in progress
        while (enc28j60ReadOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_TXRTS)
        {
                // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
                if( (enc28j60Read(EIR) & EIR_TXERIF) ) {
                        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
                        enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
                }
        }
	// Set the write pointer to start of transmit buffer area
	enc28j60Write(EWRPTL, TXSTART_INIT&0xFF);
	enc28j60Write(EWRPTH, TXSTART_INIT>>8);
	// Set the TXND pointer to correspond to the packet size given
	enc28j60Write(ETXNDL, (TXSTART_INIT+len)&0xFF);
	enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);
	// write per-packet control byte (0x00 means use macon3 settings)
	enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
	// copy the packet into the transmit buffer
	enc28j60WriteBuffer(len, packet);
	// send the contents of the transmit buffer onto the network
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
}


// Gets a packet from the network receive buffer, if one is available.
// The packet will by headed by an ethernet header.
//      maxlen  The maximum acceptable length of a retrieved packet.
//      packet  Pointer where packet data should be stored.
// Returns: Packet length in bytes if a packet was retrieved, zero otherwise.
unsigned int enc28j60BeginPacketReceive(void)
{
	unsigned int rxstat;
	unsigned int len;

	// check if a packet has been received and buffered
	//if( !(enc28j60Read(EIR) & EIR_PKTIF) ){
        // The above does not work. See Rev. B4 Silicon Errata point 6.
	if( enc28j60Read(EPKTCNT) ==0 )
		{
		return(0);
        }

	// Set the read pointer to the start of the received packet
	enc28j60Write(ERDPTL, (NextPacketPtr));
	enc28j60Write(ERDPTH, (NextPacketPtr)>>8);

	// read the next packet pointer
	NextPacketPtr  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
	NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;

	// read the packet length (see datasheet page 43)
	len  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
	len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;

    len-=4; //remove the CRC count
	// read the receive status (see datasheet page 43)
	rxstat  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
	rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;

        // check CRC and symbol errors (see datasheet page 44, table 7-3):
        // The ERXFCON.CRCEN is set by default. Normally we should not
        // need to check this.
    if ((rxstat & 0x80)==0)
	{
    	// invalid
    	len=0;
	}

	return(len);
}

void enc28j60PacketReceive(unsigned char* packet, unsigned int length)
{
	// copy the packet from the receive buffer
	enc28j60ReadBuffer(length, packet);
}

void enc28j60EndPacketReceive(void)
{
	// Move the RX read pointer to the start of the next received packet
	// This frees the memory we just read out
	enc28j60Write(ERXRDPTL, (NextPacketPtr));
	enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);

	// decrement the packet counter indicate we are done with this packet
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
}


